package org.example.utils;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.example.exception.exception.MassageException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.client.RestTemplate;

import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;

@Component
@RequiredArgsConstructor
@Slf4j
public class HttpRequestUtil {

    @Value("${http.houtai.url}")
    private String URL;
    // 发送http请求
    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;


    /**
     * @param url     情趣路径
     * @param data    请求携带的参数
     * @param resData 期待返回的对象
     * @param resType 期待返回的独享字节码
     * @param <V>     参数对象的泛型
     * @return 期待返回值的对象
     */
    public <V> V getRESTful(String url, String data, V resData, Class<V> resType) {
        //拼接请求路径
        url = getURL(url) + "/" + data;
        //发送请求
        return execute(url, HttpMethod.GET, null, null, resData, resType,false);
    }

    /**
     * @param url     情趣路径
     * @param data    请求携带的参数
     * @param resData 期待返回的对象
     * @param resType 期待返回的独享字节码
     * @param <V>     参数对象的泛型
     * @return 期待返回值的对象
     */
    public <V, T> V getRequest(String url, T data, V resData, Class<V> resType) {
        //拼接请求路径
        url = getURL(url);
        return execute(url, HttpMethod.GET, data, null, resData, resType,true);
    }

    public <V, T> V postRequest(String url, T data, V resData, Class<V> resType) {
        //拼接请求路径
        url = getURL(url);
        return execute(url, HttpMethod.POST, data, null, resData, resType, true);
    }

    //设置url
    private String getURL(String url) {
        return URL + url;
    }

    //发送请求

    /**
     * @param url     请求路径
     * @param method  请求方式
     * @param data    请求携带的参数
     * @param type    携带参数的字节码文件,用于转换json
     * @param resData 期待返回值的对象
     * @param resType 期待返回值的独享自己吗文件
     * @param <L>     携带参数相关的泛型
     * @param <V>     期待返回值对象的泛型
     * @param isJsonDate 是否是json格式的数据
     * @return 期待类型的对象
     */
    private <L, V> V execute(String url, HttpMethod method, L data, Class<L> type, V resData, Class<V> resType, boolean isJsonDate) {
        String json = restTemplate.execute(url, method, req -> {
            //设置请求头
            req.getHeaders().add("H1", "true");
            if (method.equals(HttpMethod.POST)|| isJsonDate) {
                req.getHeaders().setContentType(org.springframework.http.MediaType.parseMediaType("application/json; charset=UTF-8"));
            }

            log.info("发请求{} =>请求方式{}  ==>请求参数{}", url, method, data);
            //设置请求体 携带对应的数据 将对应的对象转成json字符串
            // 将对象转换为 JSON 字符串
            String jsonBody = objectMapper.writeValueAsString(data);
            //设置请求体
            OutputStream out = req.getBody();
            out.write(jsonBody.getBytes(StandardCharsets.UTF_8));
            out.flush();
            log.info("转换成的json->{}", jsonBody);
        }, response -> {
            // 处理响应
            log.info("接相应");
            if (response.getStatusCode().is2xxSuccessful()) {
                // 读取响应内容
                byte[] body = response.getBody().readAllBytes();
                log.debug("相应内容{}", new String(body));
                return new String(body);
            } else {
                throw new RuntimeException("请求失败，状态码: " + response.getStatusCode());
            }
        });
        //将json转成对象
        try {
            //将字符串转成map
            Map bean = JSONUtil.toBean(json, Map.class);
            //判断服务器正常处理请求
            if (KuaiZuConst.RETURN_ERROR_CODE.equals(bean.get("code"))) {
                throw new MassageException(bean.get("message").toString());
            }
            resData = objectMapper.readValue(json, resType);
            //判断服务器是否正确响应
        }catch (MassageException e){
            throw new MassageException(e.getMessage());
        } catch (JsonMappingException e){
            throw new MassageException("序列化失败");
        } catch (JsonProcessingException e){
            throw new MassageException("序列化失败");
        }
        //判断对象是否为null使用hutool包的工具
        if (Objects.isNull(resData)) {
            throw new MassageException("序列化失败");
        }
        //log.info("转换的json独享{}", resData);
        return resData;
    }


}
